builder: Fix parsing of mixed declarations
authorMatthias Clasen <mclasen@redhat.com>
Fri, 24 Sep 2021 20:34:48 +0000 (16:34 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 27 Sep 2021 21:47:24 +0000 (17:47 -0400)
The GtkBuilder parser constructs the object e.g.
when handling a <binding> element. There may be
more <property> elements after it, which we were
just not applying. Fix that by always applying
property when we see </object>. To do that, we
need to track the applied status per property.

Test included.

Fixes: #4208
gtk/gtkbuilder.c
gtk/gtkbuilderparser.c
gtk/gtkbuilderprivate.h
testsuite/reftests/late-property.ref.ui [new file with mode: 0644]
testsuite/reftests/late-property.ui [new file with mode: 0644]
testsuite/reftests/meson.build

index a151ec78cf626106142e9d8635f007e051429315..47af4df1fe6ad396aa9619bbc20a863e5bf38506 100644 (file)
@@ -540,6 +540,9 @@ gtk_builder_get_parameters (GtkBuilder         *builder,
       const char *property_name = prop->pspec->name;
       GValue property_value = G_VALUE_INIT;
 
+      if (prop->applied)
+        continue;
+
       if (prop->value)
         {
           g_value_init (&property_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
@@ -582,6 +585,9 @@ gtk_builder_get_parameters (GtkBuilder         *builder,
                   continue;
                 }
               /* Delay setting property */
+
+              prop->applied = TRUE;
+
               property = g_slice_new (DelayedProperty);
               property->pspec = prop->pspec;
               property->object = g_strdup (object_name);
@@ -612,9 +618,15 @@ gtk_builder_get_parameters (GtkBuilder         *builder,
       g_assert (G_IS_VALUE (&property_value));
 
       if ((prop->pspec->flags & filter_flags) != 0 && filtered_parameters)
-        object_properties_add (filtered_parameters, property_name, &property_value);
+        {
+          object_properties_add (filtered_parameters, property_name, &property_value);
+          prop->applied = TRUE;
+        }
       else if ((prop->pspec->flags & filter_flags) == 0 && parameters)
-        object_properties_add (parameters, property_name, &property_value);
+        {
+          object_properties_add (parameters, property_name, &property_value);
+          prop->applied = TRUE;
+        }
       else
         g_value_unset (&property_value);
     }
index c5b4039781f26dee2552eb1adce9e983fe0f90c1..f91523d5987cf9f434c695f446131eabfde1c2f4 100644 (file)
@@ -470,9 +470,6 @@ builder_construct (ParserData  *data,
 
   g_assert (object_info != NULL);
 
-  if (object_info->object && object_info->applied_properties)
-    return object_info->object;
-
   if (object_info->object == NULL)
     {
       object = _gtk_builder_construct (data->builder, object_info, error);
@@ -488,8 +485,6 @@ builder_construct (ParserData  *data,
       _gtk_builder_apply_properties (data->builder, object_info, error);
     }
 
-  object_info->applied_properties = TRUE;
-
   g_assert (G_IS_OBJECT (object));
 
   object_info->object = object;
index 913fa263a92e10d7d0a68e19da3d316cf05c8d25..32cb470f4b89867ccb46f1be96b4ec4541ad46fd 100644 (file)
@@ -53,7 +53,6 @@ typedef struct {
 
   GObject *object;
   CommonInfo *parent;
-  gboolean applied_properties;
 } ObjectInfo;
 
 typedef struct {
@@ -71,8 +70,9 @@ typedef struct {
   GParamSpec *pspec;
   gpointer value;
   GString *text;
-  gboolean translatable:1;
-  gboolean bound:1;
+  gboolean translatable : 1;
+  gboolean bound        : 1;
+  gboolean applied      : 1;
   char *context;
   int line;
   int col;
diff --git a/testsuite/reftests/late-property.ref.ui b/testsuite/reftests/late-property.ref.ui
new file mode 100644 (file)
index 0000000..f079ea7
--- /dev/null
@@ -0,0 +1,18 @@
+<interface>
+  <object class="GtkWindow">
+    <child type="titlebar">
+      <object class="GtkHeaderBar">
+        <property name="title-widget">
+          <object class="GtkLabel">
+            <property name="label">Title widget</property>
+          </object>
+        </property>
+        <child type="start">
+          <object class="GtkButton">
+            <property name="label">Button</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/testsuite/reftests/late-property.ui b/testsuite/reftests/late-property.ui
new file mode 100644 (file)
index 0000000..5283860
--- /dev/null
@@ -0,0 +1,18 @@
+<interface>
+  <object class="GtkWindow">
+    <child type="titlebar">
+      <object class="GtkHeaderBar">
+        <child type="start">
+          <object class="GtkButton">
+            <property name="label">Button</property>
+          </object>
+        </child>
+        <property name="title-widget">
+          <object class="GtkLabel">
+            <property name="label">Title widget</property>
+          </object>
+        </property>
+      </object>
+    </child>
+  </object>
+</interface>
index ea967f2d0c3ab520dd9a58bd1ed0a69bffa09d77..e4e860fc9fad19d8affd069013141c35baa1c66f 100644 (file)
@@ -331,6 +331,8 @@ testdata = [
   # that are not valid with subpixel positioning
   #'label-wrap-justify.ref.ui',
   #'label-wrap-justify.ui',
+  'late-property.ui',
+  'late-property.ref.ui',
   'letter-spacing.css',
   'letter-spacing.ui',
   'letter-spacing.ref.ui',